package Test;

import Test.Annoation.Create;
import Test.Annoation.Insert;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

// TODO: 2024/4/2
public class ApplicationContext implements Application{

    private HashMap<Class<?>,Object> map=new HashMap<>();
    private String rootPath;
    @Override
    public Object getClass(Class clazz) {
        return map.get(clazz);
    }

    public ApplicationContext(String bagPack)throws  Exception{

        try {
            //替换.为\
            String file=bagPack.replaceAll("\\.","\\\\");

            Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(file);

            while(urls.hasMoreElements()){
                URL next=urls.nextElement();
                String filePath= URLDecoder.decode(next.getFile(),"utf-8");
                rootPath=filePath.substring(0,filePath.length()-bagPack.length());
                LoadBean(new File(filePath));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        //属性注入
        Insert();
    }

    /**
     * 属性注入
     */
    private void Insert() throws Exception {
        //因为包下面的所有类都被实例化了，所以可以直接通过获取map中的对象，通过判断对象中的每一个属性是否有@Insert注解判断是否注入
        Set<Map.Entry<Class<?>, Object>> entries = map.entrySet();
        for(Map.Entry<Class<?>, Object> entrySet:entries){
            Object value=entrySet.getValue();
            //获取class
            Class<?> clazz = value.getClass();
            //获取属性
            Field[] fields = clazz.getFields();
            for(Field field:fields){
                //判断是否有注解
                Insert annotation = field.getAnnotation(Insert.class);
                if(annotation!=null){
                    //设置私有属性可以访问
                    field.setAccessible(true);
                    //注入
                    field.set(value,map.get(field.getType()));
                }

            }
        }

    }

    /**
     * 实例化
     * @param file
     * @throws Exception
     */
    private void LoadBean(File file) throws Exception {
        if(file.isDirectory()){
            File[] list=file.listFiles();
            if(list==null||list.length==0) return;
            for(File next:list){
                if(next.isDirectory())LoadBean(next);
                else{
                    String pathOfClass = next.getAbsolutePath().substring(rootPath.length() - 1);
                    if(pathOfClass.contains(".class")){
                        pathOfClass.replaceAll("\\\\",".").
                                replace(".class","");
                        
                        //获取class对象
                        Class<?> clazz = Class.forName(pathOfClass);
                        //判断是否是接口
                        if(!clazz.isInterface()){
                            //判断是否有对应注解
                            Create annotation = clazz.getAnnotation(Create.class);
                            if(annotation!=null){
                                //有注解，实例化这个对象
                                Object o = clazz.getConstructor().newInstance();
                                //放入map表中
                                //如果当前的这个类有接口，就让这个接口class作为key
                                if(clazz.getInterfaces().length>0) {
                                    //这里就取接口列表的第一个，真正的实际运用可能会有多个接口
                                    map.put(clazz.getInterfaces()[0], o);
                                }else{
                                    map.put(clazz, o);
                                }
                            }
                        }
                    }
                }
            }
        }
    }


}
